package org.example;

public class Parser {
    private Lexer lexer;
    private String currentToken;
    public Parser(Lexer lexer) {
        this.lexer = lexer;
        this.currentToken = lexer.nextToken();  // 初始化当前 token
    }
    // 解析表达式（用于计算）
    public double expr() throws Exception {
        double result = term();
        while (currentToken != null && (currentToken.equals("+") || currentToken.equals("-"))) {
            String op = currentToken;
            eat(op); // 吃掉运算符
            if (op.equals("+")) {
                result += term();
            } else {
                result -= term();
            }
        }
        return result;
    }

    // 解析项（支持 *, / 运算）
    private double term() throws Exception {
        double result = factor();
        while (currentToken != null && (currentToken.equals("*") || currentToken.equals("/"))) {
            String op = currentToken;
            eat(op);
            if (op.equals("*")) {
                result *= factor();
            } else {
                result /= factor();
            }
        }
        return result;
    }
    // 解析因子（支持括号和幂运算）
    private double factor() throws Exception {
        double result = 0;
        if (currentToken != null && currentToken.equals("(")) {
            eat("(");
            result = expr(); // 递归解析括号内的表达式
            eat(")");
        } else if (currentToken != null && isNumber(currentToken)) {
            result = Double.parseDouble(currentToken);
            eat(currentToken); // 吃掉数字
        } else if (currentToken != null && currentToken.equals("-")) {
            eat("-"); // 处理负数
            result = -factor();
        } else if (currentToken != null && currentToken.equals("+")) {
            eat("+"); // 处理正数
            result = factor();
        } else {
            throw new Exception("非法字符: " + currentToken);
        }

        // 如果是幂运算符，则进行处理
        if (currentToken != null && currentToken.equals("^")) {
            eat("^"); // 吃掉幂运算符
            result = Math.pow(result, factor()); // 执行幂运算
        }

        return result;
    }

    // 吃掉当前 token，并移到下一个 token
    private void eat(String token) {
        if (currentToken != null && currentToken.equals(token)) {
            currentToken = lexer.nextToken();
        } else {
            throw new RuntimeException("非法字符: " + token + " 目前字符: " + currentToken);
        }
    }

    // 判断是否是一个数字
    private boolean isNumber(String token) {
        try {
            Double.parseDouble(token);  // 尝试将 token 转换为数字
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
}
